001 /*
002 * Copyright 2004-2005 The Apache Software Foundation
003 * Copyright 2005 Stephen McConnell
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package net.dpml.cli.commandline;
018
019 import java.util.ArrayList;
020 import java.util.Collections;
021 import java.util.HashMap;
022 import java.util.Iterator;
023 import java.util.List;
024 import java.util.Map;
025 import java.util.Properties;
026 import java.util.Set;
027
028 import net.dpml.cli.Argument;
029 import net.dpml.cli.Option;
030 import net.dpml.cli.WriteableCommandLine;
031 import net.dpml.cli.resource.ResourceConstants;
032 import net.dpml.cli.resource.ResourceHelper;
033
034 /**
035 * A WriteableCommandLine implementation allowing Options to write their
036 * processed information to a CommandLine.
037 *
038 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
039 * @version 1.0.0
040 */
041 public class WriteableCommandLineImpl extends CommandLineImpl implements WriteableCommandLine
042 {
043 private final Properties m_properties = new Properties();
044 private final List m_options = new ArrayList();
045 private final Map m_nameToOption = new HashMap();
046 private final Map m_values = new HashMap();
047 private final Map m_switches = new HashMap();
048 private final Map m_defaultValues = new HashMap();
049 private final Map m_defaultSwitches = new HashMap();
050 private final List m_normalised;
051 private final Set m_prefixes;
052
053 /**
054 * Creates a new WriteableCommandLineImpl rooted on the specified Option, to
055 * hold the parsed arguments.
056 *
057 * @param rootOption the CommandLine's root Option
058 * @param arguments the arguments this CommandLine represents
059 */
060 public WriteableCommandLineImpl(
061 final Option rootOption, final List arguments )
062 {
063 m_prefixes = rootOption.getPrefixes();
064 m_normalised = arguments;
065 }
066
067 /**
068 * Add an option.
069 * @param option the option to add
070 */
071 public void addOption( Option option )
072 {
073 m_options.add( option );
074 m_nameToOption.put( option.getPreferredName(), option );
075 for( Iterator i = option.getTriggers().iterator(); i.hasNext();)
076 {
077 m_nameToOption.put( i.next(), option );
078 }
079 }
080
081 /**
082 * Add an option.
083 * @param option the option to add
084 * @param value the option value
085 */
086 public void addValue( final Option option, final Object value )
087 {
088 if( option instanceof Argument )
089 {
090 addOption( option );
091 }
092 List valueList = (List) m_values.get( option );
093 if( valueList == null )
094 {
095 valueList = new ArrayList();
096 m_values.put( option, valueList );
097 }
098 valueList.add( value );
099 }
100
101 /**
102 * Add a switch.
103 * @param option the option to add
104 * @param value the option value
105 */
106 public void addSwitch( final Option option, final boolean value )
107 {
108 addOption( option );
109 if( m_switches.containsKey( option ) )
110 {
111 throw new IllegalStateException(
112 ResourceHelper.getResourceHelper().getMessage(
113 ResourceConstants.SWITCH_ALREADY_SET ) );
114 }
115 else
116 {
117 if( value )
118 {
119 m_switches.put( option, Boolean.TRUE );
120 }
121 else
122 {
123 m_switches.put( option, Boolean.FALSE );
124 }
125 }
126 }
127
128 /**
129 * Detects the presence of an option in this CommandLine.
130 *
131 * @param option the Option to search for
132 * @return true iff the option is present
133 */
134 public boolean hasOption( final Option option )
135 {
136 return m_options.contains( option );
137 }
138
139 /**
140 * Finds the Option with the specified trigger
141 *
142 * @param trigger the name of the option to retrieve
143 * @return the Option matching the trigger or null if none exists
144 */
145 public Option getOption( final String trigger )
146 {
147 return (Option) m_nameToOption.get( trigger );
148 }
149
150 /**
151 * Retrieves the Argument values associated with the specified Option
152 *
153 * @param option the Option associated with the values
154 * @param defaultValues the result to return if no values are found
155 * @return a list of values or defaultValues if none are found
156 */
157 public List getValues( final Option option, final List defaultValues )
158 {
159 // First grab the command line values
160 List valueList = (List) m_values.get( option );
161
162 // Secondly try the defaults supplied to the method
163 if( ( valueList == null ) || valueList.isEmpty() )
164 {
165 valueList = defaultValues;
166 }
167
168 // Thirdly try the option's default values
169 if( ( valueList == null ) || valueList.isEmpty() )
170 {
171 valueList = (List) m_defaultValues.get( option );
172 }
173
174 // Finally use an empty list
175 if( valueList == null )
176 {
177 valueList = Collections.EMPTY_LIST;
178 }
179
180 return valueList;
181 }
182
183 /**
184 * Retrieves the Boolean value associated with the specified Switch
185 *
186 * @param option the Option associated with the value
187 * @param defaultValue the Boolean to use if none match
188 * @return the Boolean associated with option or defaultValue if none exists
189 */
190 public Boolean getSwitch( final Option option, final Boolean defaultValue )
191 {
192 // First grab the command line values
193 Boolean bool = (Boolean) m_switches.get( option );
194
195 // Secondly try the defaults supplied to the method
196 if( bool == null )
197 {
198 bool = defaultValue;
199 }
200
201 // Thirdly try the option's default values
202 if( bool == null )
203 {
204 bool = (Boolean) m_defaultSwitches.get( option );
205 }
206
207 return bool;
208 }
209
210 /**
211 * Add a property to the commandline.
212 * @param property the property name
213 * @param value the property value
214 */
215 public void addProperty( final String property, final String value )
216 {
217 m_properties.setProperty( property, value );
218 }
219
220 /**
221 * Retrieves the value associated with the specified property
222 *
223 * @param property the property name to lookup
224 * @param defaultValue the value to use if no other is found
225 * @return the value of the property or defaultValue
226 */
227 public String getProperty( final String property, final String defaultValue )
228 {
229 return m_properties.getProperty( property, defaultValue );
230 }
231
232 /**
233 * Retrieves the set of all property names associated with this CommandLine
234 *
235 * @return a none null set of property names
236 */
237 public Set getProperties()
238 {
239 return Collections.unmodifiableSet( m_properties.keySet() );
240 }
241
242 /**
243 * Return true if the trigger argument looks like an option.
244 * @param trigger the trigger to evaluate
245 * @return true if the trigger looks like an option
246 */
247 public boolean looksLikeOption( final String trigger )
248 {
249 for( final Iterator i = m_prefixes.iterator(); i.hasNext();)
250 {
251 final String prefix = (String) i.next();
252 if( trigger.startsWith( prefix ) )
253 {
254 return true;
255 }
256 }
257 return false;
258 }
259
260 /**
261 * Return this commandline as a string.
262 * @return the string representation
263 */
264 public String toString()
265 {
266 final StringBuffer buffer = new StringBuffer();
267 // need to add group header
268 for( final Iterator i = m_normalised.iterator(); i.hasNext();)
269 {
270 final String arg = ( String ) i.next();
271 if( arg.indexOf( ' ' ) >= 0 )
272 {
273 buffer.append( "\"" ).append( arg ).append( "\"" );
274 }
275 else
276 {
277 buffer.append( arg );
278 }
279 if( i.hasNext() )
280 {
281 buffer.append( ' ' );
282 }
283 }
284 return buffer.toString();
285 }
286
287 /**
288 * Retrieves a list of all Options found in this CommandLine
289 *
290 * @return a none null list of Options
291 */
292 public List getOptions()
293 {
294 return Collections.unmodifiableList( m_options );
295 }
296
297 /**
298 * Retrieves a list of all Option triggers found in this CommandLine
299 *
300 * @return a none null list of Option triggers
301 */
302 public Set getOptionTriggers()
303 {
304 return Collections.unmodifiableSet( m_nameToOption.keySet() );
305 }
306
307 /**
308 * Set default values.
309 * @param option the option
310 * @param defaults a list of defaults
311 */
312 public void setDefaultValues( final Option option, final List defaults )
313 {
314 if( defaults == null )
315 {
316 m_defaultValues.remove( option );
317 }
318 else
319 {
320 m_defaultValues.put( option, defaults );
321 }
322 }
323
324 /**
325 * Set default switch.
326 * @param option the option
327 * @param defaultSwitch the default switch state
328 */
329 public void setDefaultSwitch( final Option option, final Boolean defaultSwitch )
330 {
331 if( defaultSwitch == null )
332 {
333 m_defaultSwitches.remove( defaultSwitch );
334 }
335 else
336 {
337 m_defaultSwitches.put( option, defaultSwitch );
338 }
339 }
340
341 /**
342 * Return the normalized collection.
343 * @return the moprmalized collection
344 */
345 public List getNormalised()
346 {
347 return Collections.unmodifiableList( m_normalised );
348 }
349 }